// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.assets.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.AssetsProjectTypeEnum;
import com.liuxinlong.enums.AssetsStatusEnum;
import com.liuxinlong.enums.AssetsTypeEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.assets.dto.AssetsCostDto;
import com.liuxinlong.modules.assets.dto.AssetsOrderForecastDto;
import com.liuxinlong.modules.assets.dto.ForecastDataDto;
import com.liuxinlong.modules.assets.dto.ImportAssetsInfoDto;
import com.liuxinlong.modules.assets.service.AssetsOrderService;
import com.liuxinlong.modules.assets.service.AssetsService;
import com.liuxinlong.modules.dao.AssetsAdvancePayDao;
import com.liuxinlong.modules.dao.AssetsBudgetDao;
import com.liuxinlong.modules.dao.AssetsCostDao;
import com.liuxinlong.modules.dao.AssetsDao;
import com.liuxinlong.modules.dao.AssetsMonthDetailDao;
import com.liuxinlong.modules.dao.AssetsOrderBaseDao;
import com.liuxinlong.modules.dao.AssetsOrderDao;
import com.liuxinlong.modules.dao.AssetsOrderExpandDao;
import com.liuxinlong.modules.dao.AssetsOrderPayDao;
import com.liuxinlong.modules.dao.AssetsSourceRelationDao;
import com.liuxinlong.modules.dao.AssetsStatisticsDao;
import com.liuxinlong.modules.dao.AssetsSupplierDao;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentDepartmentSpecialDao;
import com.liuxinlong.modules.dao.RoleDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.dao.UserRoleRelationDao;
import com.liuxinlong.modules.entity.Assets;
import com.liuxinlong.modules.entity.AssetsAdvancePay;
import com.liuxinlong.modules.entity.AssetsBudget;
import com.liuxinlong.modules.entity.AssetsCost;
import com.liuxinlong.modules.entity.AssetsMonthDetail;
import com.liuxinlong.modules.entity.AssetsOrder;
import com.liuxinlong.modules.entity.AssetsOrderBase;
import com.liuxinlong.modules.entity.AssetsOrderExpand;
import com.liuxinlong.modules.entity.AssetsOrderPay;
import com.liuxinlong.modules.entity.AssetsSourceRelation;
import com.liuxinlong.modules.entity.AssetsStatistics;
import com.liuxinlong.modules.entity.PatentDepartment;
import com.liuxinlong.modules.entity.PatentDepartmentSpecial;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.entity.UserRole;
import com.liuxinlong.modules.entity.UserRoleRelation;
import com.liuxinlong.modules.out.service.OutOrderPayService;
import com.liuxinlong.utils.DecimalUtils;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 固资管理业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2023-10-31
 */
@Service
@Slf4j
public class AssetsServiceImpl implements AssetsService {
    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private AssetsDao assetsDao;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private AssetsSourceRelationDao assetsSourceRelationDao;

    @Autowired
    private AssetsBudgetDao assetsBudgetDao;

    @Autowired
    private AssetsMonthDetailDao assetsMonthDetailDao;

    @Autowired
    private AssetsOrderService assetsOrderService;

    @Autowired
    private AssetsOrderDao assetsOrderDao;

    @Autowired
    private AssetsCostDao assetsCostDao;

    @Autowired
    private AssetsAdvancePayDao assetsAdvancePayDao;

    @Autowired
    private AssetsStatisticsDao assetsStatisticsDao;

    @Autowired
    private OutOrderPayService outOrderPayService;

    @Autowired
    private AssetsOrderPayDao assetsOrderPayDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserRoleRelationDao userRoleRelationDao;

    @Autowired
    private PatentDepartmentSpecialDao patentDepartmentSpecialDao;

    @Autowired
    private AssetsOrderBaseDao assetsOrderBaseDao;

    @Autowired
    private AssetsSupplierDao assetsSupplierDao;

    @Autowired
    private AssetsOrderExpandDao assetsOrderExpandDao;

    @Override
    @Transactional
    public Map<String, Object> pageAssetsInfo(Map<String, Object> queryParam) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        Map<String, Object> dataMap = new HashMap<>();
        List<UserRoleRelation> userRoleRelationList = userRoleRelationDao.queryRelationByUserId(userId);
        UserRole highRole = roleDao.getRoleBySn("J020");
        List<UserRoleRelation> existHighList;
        if (ObjectUtils.isEmpty(highRole)) {
            existHighList = new ArrayList<>();
        } else {
            existHighList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), highRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("highPermission", !existHighList.isEmpty());
        UserRole manageRole = roleDao.getRoleBySn("J021");
        List<UserRoleRelation> existList;
        if (ObjectUtils.isEmpty(manageRole)) {
            existList = new ArrayList<>();
        } else {
            existList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), manageRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("managePermission", !existList.isEmpty());
        UserRole superManageRole = roleDao.getRoleBySn("J022");
        List<UserRoleRelation> existSuperList;
        if (ObjectUtils.isEmpty(superManageRole)) {
            existSuperList = new ArrayList<>();
        } else {
            existSuperList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), superManageRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("superPermission", !existSuperList.isEmpty());
        boolean depManage = false;
        List<PatentDepartment> departmentList = patentDepartmentDao.getDepartmentByManager(userId);
        if (!ObjectUtils.isEmpty(departmentList)) {
            depManage = true;
            List<String> depList = departmentList.stream().map(PatentDepartment::getId).collect(Collectors.toList());
            queryParam.put("manageDepartment", depList);
        }
        PatentDepartmentSpecial special = patentDepartmentSpecialDao.getDepartmentSpecialById(userId);
        if (!ObjectUtils.isEmpty(special)) {
            depManage = true;
            if (queryParam.containsKey("manageDepartment")) {
                List<String> depList = (List<String>) queryParam.get("manageDepartment");
                List<String> allList = new ArrayList<>();
                allList.addAll(depList);
                allList.addAll(Arrays.asList(special.getBranch().split(",")));
                queryParam.put("manageDepartment", allList);
            } else {
                List<String> allList = Arrays.asList(special.getBranch().split(","));
                queryParam.put("manageDepartment", allList);
            }
        }
        dataMap.put("departmentPermission", !ObjectUtils.isEmpty(departmentList) || !ObjectUtils.isEmpty(special));
        if (!existHighList.isEmpty() || !existList.isEmpty() || !existSuperList.isEmpty()) {
            queryParam.put("manageDepartment", null);
//            queryParam.put("projectManage", null);
        }
        if (existHighList.isEmpty() && existList.isEmpty() && existSuperList.isEmpty() && !depManage) {
            Map<String, Object> queryOwn = new HashMap<>();
            queryOwn.put("projectManage", userId);
            int projectCount = assetsDao.getAssetsInfoCount(queryOwn);
            if (projectCount == 0) {
                dataMap.put("totalNum", 0);
                return dataMap;
            }
            PatentDepartment department = patentDepartmentDao.getDepartmentByChild(currentUser.getDepartment());
            if (ObjectUtils.isEmpty(department)) {
                dataMap.put("totalNum", 0);
                return dataMap;
            }
            queryParam.put("department", department.getId());
        }
        int startNum = (int) queryParam.get("startNum");
        List<Assets> originalList = assetsDao.pageAssetsInfo(queryParam);
        List<Map<String, Object>> resultList = completeResult(originalList, startNum, currentUser.getId());
        dataMap.put("dataList", resultList);
        int totalNum = assetsDao.getAssetsInfoCount(queryParam);
        dataMap.put("totalNum", totalNum);
        return dataMap;
    }

    @Override
    public int getAssetsInfoCount(Map<String, Object> queryParam) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        Map<String, Object> queryOwn = new HashMap<>();
        queryOwn.put("projectManage", currentUser.getId());
        int projectCount = assetsDao.getAssetsInfoCount(queryOwn);
        if (projectCount == 0) {
            return 0;
        }
        return assetsDao.getAssetsInfoCount(queryParam);
    }

    @Override
    @Transactional
    public void addAssetsInfo(Assets assetsInfo, List<AssetsSourceRelation> sourceList) {
        if (StringUtils.isNotEmpty(assetsInfo.getAssetsNo())) {
            Assets oldInfo = assetsDao.getAssetsInfoByNo(assetsInfo.getAssetsNo());
            if (!ObjectUtils.isEmpty(oldInfo)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增固资信息失败，固资号已存在！");
            }
        }
        if (sourceList.isEmpty()) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增固资信息失败，固资来源信息为空！");
        }
        String id = SnowFlake.nextIdStr();
        assetsInfo.setId(id);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsInfo.setCreateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsInfo.setCreateTime(currentTime);

        List<AssetsSourceRelation> relationList = new ArrayList<>(sourceList.size());
        List<AssetsBudget> budgetModifyList = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        for (AssetsSourceRelation sourceRelation : sourceList) {
            if (sourceRelation.getSource() < 3) {
                AssetsBudget assetsBudget = assetsBudgetDao.selectById(sourceRelation.getBudgetId());
                if (assetsBudget.getLeftAmount().compareTo(sourceRelation.getPlanAmount()) < 0) {
                    throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算号剩余可用额度不足！");
                }
                assetsBudget.setLeftAmount(assetsBudget.getLeftAmount().subtract(sourceRelation.getPlanAmount()));
                assetsBudget.setUpdateUser(currentUser.getId());
                assetsBudget.setUpdateTime(currentTime);
                budgetModifyList.add(assetsBudget);
            }
            sourceRelation.setId(SnowFlake.nextIdStr());
            sourceRelation.setAssetsId(id);
            sourceRelation.setCreateUser(currentUser.getId());
            sourceRelation.setCreateTime(currentTime);
            relationList.add(sourceRelation);
            totalAmount = totalAmount.add(sourceRelation.getPlanAmount());
        }
        if (DecimalUtils.subtract(totalAmount, assetsInfo.getGreenAmount()).compareTo(BigDecimal.ZERO) != 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算金额与绿单金额存在差异！");
        }
        assetsDao.insert(assetsInfo);
        if (!budgetModifyList.isEmpty()) {
            assetsBudgetDao.updateBatchById(budgetModifyList);
        }
        if (!relationList.isEmpty()) {
            assetsSourceRelationDao.insertBatch(relationList);
        }
        AssetsMonthDetail assetsMonthDetail = new AssetsMonthDetail();
        assetsMonthDetail.setId(SnowFlake.nextIdStr());
        assetsMonthDetail.setInfoYear(assetsInfo.getCurrentYear());
        assetsMonthDetail.setBusinessType(3);
        assetsMonthDetail.setBusinessId(id);
        assetsMonthDetail.setCreateUser(currentUser.getId());
        assetsMonthDetail.setCreateTime(currentTime);
        assetsMonthDetailDao.insert(assetsMonthDetail);
        AssetsStatistics statistics = buildStatistics(assetsInfo);
        assetsStatisticsDao.insert(statistics);
    }

    @Override
    @Transactional
    public void updateAssetsInfo(Assets assetsInfo, List<AssetsSourceRelation> sourceList) {
        String id = assetsInfo.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资信息失败，固资信息不存在！");
        }
        Assets oldInfo = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资信息失败，固资信息不存在！");
        }
        if (StringUtils.isNotEmpty(assetsInfo.getAssetsNo())) {
            Assets sameNoInfo = assetsDao.getAssetsInfoByNo(assetsInfo.getAssetsNo());
            if (!ObjectUtils.isEmpty(sameNoInfo) && !StringUtils.equals(sameNoInfo.getId(), id)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资信息失败，固资号已存在！");
            }
        }
        assetsInfo.setStatus(oldInfo.getStatus());
        assetsInfo.setCreateTime(oldInfo.getCreateTime());
        assetsInfo.setCreateUser(oldInfo.getCreateUser());
        assetsInfo.setRecommend(oldInfo.getRecommend());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsInfo.setUpdateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsInfo.setUpdateTime(currentTime);

        List<AssetsSourceRelation> oldRelationList = assetsSourceRelationDao.getAssetsSourceRelation(id);
        Map<String, BigDecimal> budgetAmountMap = new HashMap<>();
        List<String> oldRelationIdList = new ArrayList<>(oldRelationList.size());
        for (AssetsSourceRelation sourceRelation : oldRelationList) {
            oldRelationIdList.add(sourceRelation.getId());
            if (sourceRelation.getSource() < 3) {
                budgetAmountMap.put(sourceRelation.getBudgetId(), sourceRelation.getPlanAmount());
            }
        }

        List<AssetsSourceRelation> relationList = new ArrayList<>(sourceList.size());
        List<AssetsBudget> budgetModifyList = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        Map<String, Object> queryPayParam = new HashMap<>();
        queryPayParam.put("startDate", assetsInfo.getApproveTime());
        queryPayParam.put("endDate", currentTime);
        Map<String, Map<String, String>> orderPayMap = assetsOrderPayDao.getOrderPayMap(queryPayParam);
        for (AssetsSourceRelation sourceRelation : sourceList) {
            if (sourceRelation.getSource() < 3) {
                AssetsBudget assetsBudget = assetsBudgetDao.selectById(sourceRelation.getBudgetId());
                BigDecimal leftAmount = assetsBudget.getLeftAmount();
                if (budgetAmountMap.containsKey(sourceRelation.getBudgetId())) {
                    leftAmount = leftAmount.add(budgetAmountMap.get(sourceRelation.getBudgetId()));
                }
                if (leftAmount.compareTo(sourceRelation.getPlanAmount()) < 0) {
                    throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算号剩余可用额度不足！");
                }
                assetsBudget.setLeftAmount(leftAmount.subtract(sourceRelation.getPlanAmount()));
                assetsBudget.setUpdateUser(currentUser.getId());
                assetsBudget.setUpdateTime(currentTime);
                budgetModifyList.add(assetsBudget);
            }
            sourceRelation.setId(SnowFlake.nextIdStr());
            sourceRelation.setAssetsId(id);
            sourceRelation.setCreateUser(currentUser.getId());
            sourceRelation.setCreateTime(currentTime);
            relationList.add(sourceRelation);
            totalAmount = totalAmount.add(sourceRelation.getPlanAmount());
        }
        if (DecimalUtils.subtract(totalAmount, assetsInfo.getGreenAmount()).compareTo(BigDecimal.ZERO) != 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算金额与绿单金额存在差异！");
        }
        if (!oldRelationIdList.isEmpty()) {
            assetsSourceRelationDao.deleteBatchIds(oldRelationIdList);
        }
        if (!budgetModifyList.isEmpty()) {
            assetsBudgetDao.updateBatchById(budgetModifyList);
        }
        if (!relationList.isEmpty()) {
            assetsSourceRelationDao.insertBatch(relationList);
        }
        Map<String, BigDecimal> orderMap = new HashMap<>();
        if (!StringUtils.equals(assetsInfo.getAssetsNo(), oldInfo.getAssetsNo())) {
            if (!StringUtils.isEmpty(oldInfo.getAssetsNo())) {
                assetsOrderBaseDao.updateAssetIdByNo(oldInfo.getAssetsNo(), "");
            }
            if (!StringUtils.isEmpty(assetsInfo.getAssetsNo())) {
//                Map<String, Object> queryPayParam = new HashMap<>();
//                queryPayParam.put("startDate", assetsInfo.getApproveTime());
//                queryPayParam.put("endDate", currentTime);
//                Map<String, Map<String, String>> orderPayMap = assetsOrderPayDao.getOrderPayMap(queryPayParam);
                Map<String, Object> queryParam = new HashMap<>();
                queryParam.put("startNum", 0);
                queryParam.put("pageSize", 1000);
                queryParam.put("assetsNo", assetsInfo.getAssetsNo());
//                queryParam.put("startDate", TimeUtils.getCurrentYearStart());
//                queryParam.put("endDate", TimeUtils.getCurrentYearEnd());
                List<AssetsOrderBase> orderList = assetsOrderBaseDao.getAssetsOrderBaseList(queryParam);
                BigDecimal actualAmount = new BigDecimal(0);
                for (AssetsOrderBase assetsOrder : orderList) {
                    if (assetsOrder.getStatus() == 1) {
                        continue;
//                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
                    }
//                    if (assetsOrder.getStatus() == 2) {
//                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
//                    }
                    String orderNo = assetsOrder.getOrderNo();
                    if (assetsOrder.getStatus() == 2) {
                        if (orderPayMap.containsKey(orderNo)) {
                            Map<String, String> payInfo = orderPayMap.get(orderNo);
                            actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount()).subtract(new BigDecimal(payInfo.get("untaxedAmount")));
                        }
                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
                    }
                }
                assetsInfo.setCurrentYearActual(actualAmount);
                assetsOrderDao.updateAssetIdByNo(assetsInfo.getAssetsNo(), assetsInfo.getId());
            }
        }
        assetsDao.updateById(assetsInfo);
        AssetsStatistics statistics = assetsStatisticsDao.getStatisticsByAssets(id, assetsInfo.getCurrentYear());
        if (BigDecimal.ZERO.equals(DecimalUtils.subtract(statistics.getPlanAmount(), assetsInfo.getCurrentYearAmount())) &&
                BigDecimal.ZERO.equals(DecimalUtils.subtract(statistics.getForecastAmount(), assetsInfo.getCurrentYearForecast())) &&
                BigDecimal.ZERO.equals(DecimalUtils.subtract(statistics.getActualAmount(), assetsInfo.getCurrentYearActual()))) {
            return;
        }
        statistics.setPlanAmount(assetsInfo.getCurrentYearAmount());
        statistics.setForecastAmount(assetsInfo.getCurrentYearForecast());
        statistics.setActualAmount(assetsInfo.getCurrentYearActual());
        statistics.setUpdateTime(currentTime);
        statistics.setUpdateUser(currentUser.getId());
        assetsStatisticsDao.updateById(statistics);

    }

    @Override
    @Transactional
    public void deleteAssetsInfo(String id) {
        Assets assets = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，固资信息不存在！");
        }
        List<AssetsSourceRelation> assetsSourceRelationList = assetsSourceRelationDao.getAssetsSourceRelation(id);
        List<AssetsBudget> budgetList = new ArrayList<>(assetsSourceRelationList.size());
        for (AssetsSourceRelation relation : assetsSourceRelationList) {
            if (relation.getSource() == 3) {
                continue;
            }
            AssetsBudget assetsBudget = assetsBudgetDao.selectById(relation.getBudgetId());
            BigDecimal leftAmount = assetsBudget.getLeftAmount().add(relation.getPlanAmount());
            assetsBudget.setLeftAmount(leftAmount);
            budgetList.add(assetsBudget);
        }
        if (!ObjectUtils.isEmpty(budgetList)) {
            assetsBudgetDao.updateBatchById(budgetList);
        }
        assetsDao.deleteById(id);
    }

    @Override
    public void exportAssetsInfo(Map<String, Object> queryParam, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("固资导出excel.xlsx");
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<Assets> assetsInfoList = assetsDao.pageAssetsInfo(queryParam);
        Map<String, Object> query = new HashMap<>();
        query.put("businessType", 3);
        List<AssetsMonthDetail> spendingList = assetsMonthDetailDao.getEffectiveMonthInfo(query);
        Map<String, AssetsMonthDetail> spendMap = new HashMap<>();
        for (AssetsMonthDetail sp : spendingList) {
            spendMap.put(sp.getBusinessId(), sp);
        }
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        String[] head = {"展示排序", "固资号", "申请部门", "项目描述", "项目负责人", "绿单总金额", "当年计划金额", "当年预测金额", "当年实际金额", "状态", "spending预测",
                "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
        data.setHead(head);
        String[][] dataList = new String[assetsInfoList.size()][head.length];
        int index = 0;
        String year = (String) queryParam.get("year");
        for (Assets assetsInfo : assetsInfoList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = assetsInfo.getAssetsNo();
            dataList[index][2] = departmentMap.containsKey(assetsInfo.getDepartment()) ? departmentMap.get(assetsInfo.getDepartment()).get("name") : "";
            dataList[index][3] = assetsInfo.getProjectName();
            dataList[index][4] = userMap.containsKey(assetsInfo.getProjectManage()) ? userMap.get(assetsInfo.getProjectManage()).get("name") : "";
            dataList[index][5] = String.valueOf(assetsInfo.getGreenAmount());
            dataList[index][6] = String.valueOf(assetsInfo.getCurrentYearAmount());
            dataList[index][7] = String.valueOf(assetsInfo.getCurrentYearForecast());
            dataList[index][8] = String.valueOf(assetsInfo.getCurrentYearActual());
            dataList[index][9] = AssetsStatusEnum.getNameByValue(assetsInfo.getStatus());
            dataList[index][10] = year;
            AssetsMonthDetail spend = spendMap.get(assetsInfo.getId());
            dataList[index][11] = String.valueOf(spend.getJanAmount());
            dataList[index][12] = String.valueOf(spend.getFebAmount());
            dataList[index][13] = String.valueOf(spend.getMarAmount());
            dataList[index][14] = String.valueOf(spend.getAprAmount());
            dataList[index][15] = String.valueOf(spend.getMayAmount());
            dataList[index][16] = String.valueOf(spend.getJunAmount());
            dataList[index][17] = String.valueOf(spend.getJulAmount());
            dataList[index][18] = String.valueOf(spend.getAugAmount());
            dataList[index][19] = String.valueOf(spend.getSepAmount());
            dataList[index][20] = String.valueOf(spend.getOctAmount());
            dataList[index][21] = String.valueOf(spend.getNovAmount());
            dataList[index][22] = String.valueOf(spend.getDecAmount());

            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public ImportResp importAssetsInfo(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                ImportAssetsInfoDto assetsInfo = covertToBean(record);
                return false;
//				try {
//					materialStandardDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetCode(ReturnCodes.HTTP_SUCCESS.getRetCode());
                resp.setRetMessage("导入固资数据部分失败，总数=" + resp.getTotal() + ",失败总数=" +
                        resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入固资数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("plant", failRecord[1]);
                    item.put("assetsNo", failRecord[2]);
                    item.put("department", failRecord[3]);
                    item.put("projectName", failRecord[4]);
                    item.put("projectNameEng", failRecord[5]);
                    item.put("projectManage", failRecord[6]);
                    item.put("projectType", failRecord[7]);
                    item.put("currentYear", failRecord[8]);
                    item.put("greenAmount", failRecord[9]);
                    item.put("status", failRecord[10]);
                    item.put("approveTime", failRecord[11]);
                    item.put("budget", failRecord[12]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddAssetsInfo(List<ImportAssetsInfoDto> dataList) {
        Map<String, Map<String, String>> assetsMap = assetsDao.getAssetsMap();
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMapByName();
        Map<String, Map<String, String>> userMap = userDao.getUserMapBySn();
        Map<String, Map<String, String>> budgetMap = assetsBudgetDao.getAssetsBudgetMapByNo();
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<Map> failedList = new ArrayList<>();
        boolean insertSuccess;
        int sort = 1;
        List<AssetsSourceRelation> relationList = new ArrayList<>();
        List<AssetsBudget> updateList = new ArrayList<>();
        List<AssetsStatistics> statisticsList = new ArrayList<>();
        Map<String, BigDecimal> usedAmountMap = new HashMap();
        Map<String, Object> queryPayParam = new HashMap<>();
        queryPayParam.put("startDate", "2019-01-01");
        queryPayParam.put("endDate", currentTime);
        Map<String, Map<String, String>> orderPayMap = assetsOrderPayDao.getOrderPayMap(queryPayParam);
        for (ImportAssetsInfoDto assetsInfoDto : dataList) {
            Assets assetsInfo = new Assets();
            assetsInfo.setPlant(assetsInfoDto.getPlant());
            if (StringUtils.isNotEmpty(assetsInfoDto.getAssetsNo()) && assetsMap.containsKey(assetsInfoDto.getAssetsNo())) {
                Map item = ObjectUtils.object2Map(assetsInfoDto);
                item.put("message", "固资号已存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            assetsInfo.setAssetsNo(assetsInfoDto.getAssetsNo());
            if (!departmentMap.containsKey(assetsInfoDto.getDepartment())) {
                Map item = ObjectUtils.object2Map(assetsInfoDto);
                item.put("message", "申请部门不存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            assetsInfo.setDepartment(departmentMap.get(assetsInfoDto.getDepartment()).get("id"));
            assetsInfo.setProjectName(assetsInfoDto.getProjectName());
            assetsInfo.setProjectNameEng(assetsInfoDto.getProjectNameEng());
            if (assetsInfoDto.getProjectManage().contains("/")) {
                List<String> manageUserInfo = Arrays.asList(assetsInfoDto.getProjectManage().split("/"));
                List<String> userInfo = Arrays.asList(manageUserInfo.get(0).split("-"));
                if (userInfo.size() != 2 || !userMap.containsKey(userInfo.get(1))) {
                    Map item = ObjectUtils.object2Map(assetsInfoDto);
                    item.put("message", "项目负责人不存在！");
                    item.put("sort", sort);
                    failedList.add(item);
                    sort++;
                    continue;
                }
                assetsInfo.setProjectManage(userMap.get(userInfo.get(1)).get("id"));
            } else {
                List<String> userInfo = Arrays.asList(assetsInfoDto.getProjectManage().split("-"));
                if (userInfo.size() != 2 || !userMap.containsKey(userInfo.get(1))) {
                    Map item = ObjectUtils.object2Map(assetsInfoDto);
                    item.put("message", "项目负责人不存在！");
                    item.put("sort", sort);
                    failedList.add(item);
                    sort++;
                    continue;
                }
                assetsInfo.setProjectManage(userMap.get(userInfo.get(1)).get("id"));
            }
            assetsInfo.setProjectType(AssetsProjectTypeEnum.getValueByName(assetsInfoDto.getProjectType()));
            assetsInfo.setCurrentYear(assetsInfoDto.getCurrentYear());
            assetsInfo.setGreenAmount(assetsInfoDto.getGreenAmount());
            assetsInfo.setStatus(AssetsStatusEnum.getValueByName(assetsInfoDto.getStatus().toLowerCase()));
            assetsInfo.setApproveTime(assetsInfoDto.getApproveTime());

            String message = "";
            String id = SnowFlake.nextIdStr();
            assetsInfo.setId(id);
            assetsInfo.setCreateUser(currentUser.getId());
            if (!StringUtils.isEmpty(assetsInfo.getAssetsNo())) {
                Map<String, Object> queryParam = new HashMap<>();
                queryParam.put("startNum", 0);
                queryParam.put("pageSize", 1000);
                queryParam.put("assetsNo", assetsInfo.getAssetsNo());
                queryParam.put("startDate", TimeUtils.getCurrentYearStart());
                queryParam.put("endDate", TimeUtils.getCurrentYearEnd());
                List<AssetsOrder> orderList = assetsOrderDao.getAssetsOrderList(queryParam);
                BigDecimal actualAmount = new BigDecimal(0);
                for (AssetsOrder assetsOrder : orderList) {
                    if (assetsOrder.getStatus() == 1) {
                        continue;
//                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
                    }
                    if (assetsOrder.getStatus() == 2) {
                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
                    }
                    String orderNo = assetsOrder.getOrderNo();
                    if (assetsOrder.getStatus() == 3) {
                        if (orderPayMap.containsKey(orderNo)) {
                            Map<String, String> payInfo = orderPayMap.get(orderNo);
                            actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount()).subtract(new BigDecimal(payInfo.get("untaxedAmount")));
                        }
                        actualAmount = actualAmount.add(assetsOrder.getUntaxedAmount());
                    }
                }
                assetsInfo.setCurrentYearActual(actualAmount);
                assetsOrderDao.updateAssetIdByNo(assetsInfo.getAssetsNo(), assetsInfo.getId());
            }
            try {
                assetsDao.insert(assetsInfo);
                insertSuccess = true;
            } catch (Exception e) {
                insertSuccess = false;
                message = e.getMessage();
            }
//            }
            if (!insertSuccess) {
                Map<String, Object> map = ObjectUtils.object2Map(assetsInfoDto);
                map.put("sort", sort);
                map.put("message", message);
                sort++;
                failedList.add(map);
                continue;
            }
            // 固资来源信息
            List<String> budgetList = Arrays.asList(assetsInfoDto.getBudget().split(","));
            for (String budget : budgetList) {
                List<String> source = Arrays.asList(budget.split("/"));
                if (source.size() < 2) {
                    continue;
                }
                String budgetNo = source.get(0);
                BigDecimal budgetAmount = new BigDecimal(source.get(1));
                AssetsSourceRelation assetsSourceRelation = new AssetsSourceRelation();
                assetsSourceRelation.setId(SnowFlake.nextIdStr());
                assetsSourceRelation.setAssetsId(id);
                if (budgetMap.containsKey(budgetNo)) {
                    Map<String, String> budgetInfo = budgetMap.get(budgetNo);
                    String budgetId = budgetInfo.get("id");
                    BigDecimal usedAmount = usedAmountMap.containsKey(budgetId) ? usedAmountMap.get(budgetId) : new BigDecimal(0);
                    usedAmount = usedAmount.add(budgetAmount);
                    usedAmountMap.put(budgetId, usedAmount);

                }
                assetsSourceRelation.setBudgetId(budgetMap.containsKey(budgetNo) ? budgetMap.get(budgetNo).get("id") : budgetNo);
                assetsSourceRelation.setPlanAmount(budgetAmount);
                assetsSourceRelation.setSource(budgetMap.containsKey(budgetNo) ? 2 : 3);
                assetsSourceRelation.setCreateTime(currentTime);
                assetsSourceRelation.setCreateUser(currentUser.getId());
                relationList.add(assetsSourceRelation);
            }
            if (!ObjectUtils.isEmpty(usedAmountMap)) {
                List<AssetsBudget> oldList = assetsBudgetDao.selectBatchIds(usedAmountMap.keySet());
                for (AssetsBudget budget : oldList) {
                    if (!usedAmountMap.containsKey(budget.getId())) {
                        continue;
                    }
                    BigDecimal leftAmount = budget.getLeftAmount();
                    leftAmount = leftAmount.subtract(usedAmountMap.get(budget.getId()));
                    budget.setLeftAmount(leftAmount);
                    budget.setUpdateUser(currentUser.getId());
                    budget.setUpdateTime(currentTime);
                    updateList.add(budget);
                }
            }
            AssetsStatistics statistics = buildStatistics(assetsInfo);
            statisticsList.add(statistics);
        }
        if (statisticsList.size() > 0) {
            assetsStatisticsDao.insertBatch(statisticsList);
        }
        if (relationList.size() > 0) {
            assetsSourceRelationDao.insertBatch(relationList);
        }
        if (updateList.size() > 0) {
            assetsBudgetDao.updateBatchById(updateList);
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() :
                ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(dataList.size() - failedList.size());
        resp.setFailedTotal(failedList.size());
        resp.setFailedList(failedList);
        resp.setRetMessage(failedList.size() > 0 ? "导入固资信息部分成功" : "导入固资信息成功");
        return resp;
    }

    @Override
    public void updateAssetsInfoStatus(String id, int targetStatus) {
        Assets assets = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        if (targetStatus != AssetsStatusEnum.CANCEL.getValue() && StringUtils.isEmpty(assets.getAssetsNo())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资号不能为空！");
        }
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assets.setStatus(targetStatus);
        assets.setUpdateTime(currentTime);
        assets.setUpdateUser(currentUser.getId());
        assetsDao.updateById(assets);
    }

    @Override
    public Map<String, Object> queryAssetsExpandInfo(String id, String chooseYear) {
        Assets assets = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        Map<String, Object> dataMap = new HashMap<>();
        List<AssetsSourceRelation> relationList = assetsSourceRelationDao.getAssetsSourceRelation(id);
        List<Map<String, Object>> planList = new ArrayList<>();
        Map<String, Map<String, String>> budgetMap = assetsBudgetDao.getAssetsBudgetMap();
        int sort = 1;
        for (AssetsSourceRelation relation : relationList) {
            Map<String, Object> item = ObjectUtils.object2Map(relation);
            item.put("sort", sort);
            item.put("planNo", budgetMap.containsKey(relation.getBudgetId()) ? budgetMap.get(relation.getBudgetId()).get("planNo") : relation.getBudgetId());
            planList.add(item);
            sort++;
        }
        dataMap.put("planList", planList);
        String currentYear = assets.getCurrentYear();
        List<AssetsMonthDetail> monthList = assetsMonthDetailDao.getAssetsMonthInfo(id, chooseYear);
        List<Map<String, Object>> forecastList = new ArrayList<>(monthList.size());
        for (AssetsMonthDetail monthDetail : monthList) {
            Map<String, Object> item = ObjectUtils.object2Map(monthDetail);
            BigDecimal currentYearAmount = DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(
                            DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(
                                            DecimalUtils.add(DecimalUtils.add(monthDetail.getJanAmount(), monthDetail.getFebAmount()),
                                                    monthDetail.getMarAmount()),
                                            monthDetail.getAprAmount()), monthDetail.getMayAmount()), monthDetail.getJunAmount()),
                                    monthDetail.getJulAmount()), monthDetail.getAugAmount()), monthDetail.getSepAmount()),
                    monthDetail.getOctAmount()), monthDetail.getNovAmount()), monthDetail.getDecAmount());
            item.put("currentYearAmount", currentYearAmount);
            item.put("nextYearAmount", monthDetail.getBusinessType() < 3 ? DecimalUtils.subtract(assets.getGreenAmount(), currentYearAmount) : 0);
            forecastList.add(item);
        }
        dataMap.put("forecastList", forecastList);
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        queryParam.put("assetsId", id);
        queryParam.put("currentYear", chooseYear);
        List<Map<String, Object>> orderList = assetsOrderService.pageAssetsOrderInfo(queryParam);
        dataMap.put("orderList", orderList);
        if (orderList.isEmpty()) {
            dataMap.put("leftAmount", assets.getGreenAmount());
            dataMap.put("useRate", 0);
            return dataMap;
        }
        BigDecimal usedAmount = BigDecimal.valueOf(0);
        BigDecimal costAmount = BigDecimal.valueOf(0);
        for (Map<String, Object> ao : orderList) {
            usedAmount = usedAmount.add((BigDecimal) ao.get("untaxedAmount"));
            costAmount = DecimalUtils.add(costAmount, DecimalUtils.add((BigDecimal) ao.get("costAmount"), (BigDecimal) ao.get("lastCostAmount")));
        }
        dataMap.put("costAmount", costAmount);
        dataMap.put("leftAmount", assets.getGreenAmount().subtract(usedAmount));
        dataMap.put("useRate", usedAmount.multiply(BigDecimal.valueOf(100)).divide(assets.getGreenAmount(), 2, RoundingMode.HALF_UP));
        return dataMap;
    }

    @Override
    public List<Map<String, Object>> pageAssetsSourceInfo(String id) {
        List<AssetsSourceRelation> relationList = assetsSourceRelationDao.getAssetsSourceRelation(id);
        List<Map<String, Object>> planList = new ArrayList<>();
        Map<String, Map<String, String>> budgetMap = assetsBudgetDao.getAssetsBudgetMap();
        int sort = 1;
        for (AssetsSourceRelation relation : relationList) {
            Map<String, Object> item = ObjectUtils.object2Map(relation);
            item.put("sort", sort);
            item.put("planNo", budgetMap.containsKey(relation.getBudgetId()) ? budgetMap.get(relation.getBudgetId()).get("planNo") : relation.getBudgetId());
            planList.add(item);
            sort++;
        }
        return planList;
    }

    @Override
    @Transactional
    public void addAssetsSourceInfo(AssetsSourceRelation assetsSourceRelation) {
        Assets assets = assetsDao.selectById(assetsSourceRelation.getAssetsId());
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        List<AssetsSourceRelation> relationList = assetsSourceRelationDao.getAssetsSourceRelation(assets.getId());
        BigDecimal totalAmount = new BigDecimal(0);
        for (AssetsSourceRelation relation : relationList) {
            if (StringUtils.equals(assetsSourceRelation.getBudgetId(), relation.getBudgetId())) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同预算来源！");
            }
            totalAmount = totalAmount.add(relation.getPlanAmount());
        }
        totalAmount = totalAmount.add(assetsSourceRelation.getPlanAmount());
        assets.setGreenAmount(totalAmount);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assets.setUpdateUser(currentUser.getId());
        assets.setUpdateTime(currentTime);
        assetsDao.updateById(assets);
        if (assetsSourceRelation.getSource() < 3) {
            AssetsBudget assetsBudget = assetsBudgetDao.selectById(assetsSourceRelation.getBudgetId());
            if (assetsBudget.getLeftAmount().compareTo(assetsSourceRelation.getPlanAmount()) < 0) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算号剩余可用额度不足！");
            }
            assetsBudget.setLeftAmount(assetsBudget.getLeftAmount().subtract(assetsSourceRelation.getPlanAmount()));
            assetsBudget.setUpdateUser(currentUser.getId());
            assetsBudget.setUpdateTime(currentTime);
            assetsBudgetDao.updateById(assetsBudget);
        }
        assetsSourceRelation.setId(SnowFlake.nextIdStr());
        assetsSourceRelation.setCreateUser(currentUser.getId());
        assetsSourceRelation.setCreateTime(currentTime);
        assetsSourceRelationDao.insert(assetsSourceRelation);
    }

    @Override
    @Transactional
    public void updateAssetsSourceInfo(AssetsSourceRelation assetsSourceRelation) {
        Assets assets = assetsDao.selectById(assetsSourceRelation.getAssetsId());
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        List<AssetsSourceRelation> relationList = assetsSourceRelationDao.getAssetsSourceRelation(assets.getId());
        BigDecimal totalAmount = new BigDecimal(0);
        for (AssetsSourceRelation relation : relationList) {
            if (StringUtils.equals(relation.getId(), assetsSourceRelation.getId())) {
                continue;
            }
            if (StringUtils.equals(assetsSourceRelation.getBudgetId(), relation.getBudgetId())) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同预算来源！");
            }
            totalAmount = totalAmount.add(relation.getPlanAmount());
        }
        totalAmount = totalAmount.add(assetsSourceRelation.getPlanAmount());
        assets.setGreenAmount(totalAmount);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assets.setUpdateUser(currentUser.getId());
        assets.setUpdateTime(currentTime);
        assetsDao.updateById(assets);
        if (assetsSourceRelation.getSource() < 3) {
            AssetsBudget assetsBudget = assetsBudgetDao.selectById(assetsSourceRelation.getBudgetId());
            if (assetsBudget.getPlanAmount().compareTo(totalAmount) < 0) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "预算号剩余可用额度不足！");
            }
            assetsBudget.setLeftAmount(assetsBudget.getPlanAmount().subtract(totalAmount));
            assetsBudget.setUpdateUser(currentUser.getId());
            assetsBudget.setUpdateTime(currentTime);
            assetsBudgetDao.updateById(assetsBudget);
        }
        assetsSourceRelation.setUpdateUser(currentUser.getId());
        assetsSourceRelation.setUpdateTime(currentTime);
        assetsSourceRelationDao.updateById(assetsSourceRelation);
    }

    @Override
    @Transactional
    public void deleteAssetsSourceInfo(String id) {
        AssetsSourceRelation assetsSourceRelation = assetsSourceRelationDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsSourceRelation)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，预算来源不存在！");
        }
        AssetsBudget assetsBudget = assetsBudgetDao.selectById(assetsSourceRelation.getBudgetId());
        if (ObjectUtils.isEmpty(assetsBudget)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，预算不存在！");
        }
        BigDecimal leftAmount = assetsBudget.getLeftAmount().add(assetsSourceRelation.getPlanAmount());
        assetsBudget.setLeftAmount(leftAmount);
        assetsBudgetDao.updateById(assetsBudget);
    }

    @Override
    public Map<String, Object> pageAssetsForecastInfo(String id, String currentYear) {
        Assets assets = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        Map<String, Object> dataMap = new HashMap<>();
        if (assets.getStatus() < 3) {
            List<AssetsMonthDetail> monthList = assetsMonthDetailDao.getAssetsMonthInfo(id, currentYear);
            List<Map<String, Object>> dataList = new ArrayList<>(monthList.size());
            for (AssetsMonthDetail monthDetail : monthList) {
                Map<String, Object> item = ObjectUtils.object2Map(monthDetail);
                BigDecimal currentYearAmount = DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(
                                DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(DecimalUtils.add(
                                                DecimalUtils.add(DecimalUtils.add(monthDetail.getJanAmount(), monthDetail.getFebAmount()),
                                                        monthDetail.getMarAmount()),
                                                monthDetail.getAprAmount()), monthDetail.getMayAmount()), monthDetail.getJunAmount()),
                                        monthDetail.getJulAmount()), monthDetail.getAugAmount()), monthDetail.getSepAmount()),
                        monthDetail.getOctAmount()), monthDetail.getNovAmount()), monthDetail.getDecAmount());
                item.put("currentYearAmount", currentYearAmount);
                item.put("nextYearAmount", DecimalUtils.subtract(assets.getGreenAmount(), currentYearAmount));
                dataList.add(item);
            }
            dataMap.put("forecastList", dataList);
        } else {
            Map<String, Object> queryParam = new HashMap<>();
            queryParam.put("startNum", 0);
            queryParam.put("pageSize", 10000);
            queryParam.put("currentYear", currentYear);
            queryParam.put("assetsId", id);
            List<Map<String, Object>> orderBaseList = assetsOrderService.pageAssetsOrderInfo(queryParam);
            List<Map<String, Object>> orderList = new ArrayList<>(orderBaseList.size());
            queryParam.put("status", 1);
            String currentDate = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD);
            queryParam.put("startDate", currentDate);
            List<AssetsCost> costList = assetsCostDao.pageAssetsCostInfo(queryParam);
            Map<String, AssetsCost> costMap = new HashMap<>();
            List<String> costIdList = new ArrayList<>();
            for (AssetsCost cost : costList) {
                costMap.put(cost.getId(), cost);
                costIdList.add(cost.getId());
            }
//             costList.stream().map(AssetsCost::getId).collect(Collectors.toList());
            Map<String, List<AssetsAdvancePay>> costDetailMap = new HashMap<>();
            if (!costIdList.isEmpty()) {
                List<AssetsAdvancePay> advancePayList = assetsAdvancePayDao.getEffectiveAdvancePayList(costIdList);
                for (AssetsAdvancePay assetsAdvancePay : advancePayList) {
                    String costId = assetsAdvancePay.getCostId();
                    List<AssetsAdvancePay> payList = new ArrayList<>();
                    if (costDetailMap.containsKey(costId)) {
                        payList = costDetailMap.get(costId);
                    }
                    payList.add(assetsAdvancePay);
                    costDetailMap.put(costId, payList);
                }
            }
            List<AssetsCost> orderCostList = costList.stream().filter(item -> item.getSourceType() == 1).collect(Collectors.toList());
            Map<String, List<AssetsAdvancePay>> orderForecastMap = new HashMap<>();
            Map<String, String> orderCostMap = new HashMap<>();
            for (AssetsCost assetsCost : orderCostList) {
                orderCostMap.put(assetsCost.getSourceId(), assetsCost.getId());
                if (!costDetailMap.containsKey(assetsCost.getId())) {
                    continue;
                }
                orderForecastMap.put(assetsCost.getSourceId(), costDetailMap.get(assetsCost.getId()));
            }
            BigDecimal usedAmount = BigDecimal.valueOf(0);
//            if (!orderCostList.isEmpty()) {
            int sort = 1;
            for (Map<String, Object> orderMap : orderBaseList) {
                if ((int) orderMap.get("status") == 2) {
                    usedAmount = usedAmount.add((BigDecimal) orderMap.get("untaxedAmount"));
                    continue;
                }
//                if ((int) orderMap.get("status") == 1) {
                usedAmount = usedAmount.add((BigDecimal) orderMap.get("untaxedAmount"));
//                }
                List<AssetsAdvancePay> subList = new ArrayList<>();
                String orderId = (String) orderMap.get("id");
                if (orderForecastMap.containsKey(orderId)) {
                    subList = orderForecastMap.get(orderId);
                }
                orderMap.put("id", orderCostMap.get(orderId));
                orderMap.put("orderId", orderId);
                List<AssetsAdvancePay> sortSubList = subList.stream().sorted(
                        Comparator.nullsLast(Comparator.comparing(AssetsAdvancePay::getPlanPayDate,
                                Comparator.nullsLast(String::compareTo)))).collect(Collectors.toList());
                List<Map<String, Object>> newSortSubList = new ArrayList<>(sortSubList.size());
                int paySort = 1;
                for (AssetsAdvancePay assetsAdvancePay : sortSubList) {
                    Map<String, Object> payItem = ObjectUtils.object2Map(assetsAdvancePay);
                    payItem.put("sort", paySort);
                    newSortSubList.add(payItem);
                    paySort++;
                }
                orderMap.put("subList", newSortSubList);
                orderMap.put("sort", sort);
                orderList.add(orderMap);
                sort++;
            }
            dataMap.put("orderList", orderList);
//            }
            List<AssetsCost> costBaseList = costList.stream().filter(item -> item.getSourceType() == 2).collect(Collectors.toList());
            List<Map<String, Object>> resultCostList = new ArrayList<>(costBaseList.size());
            int sortCost = 1;
            for (AssetsCost cost : costBaseList) {
                Map<String, Object> item = ObjectUtils.object2Map(cost);
                item.put("sort", sortCost);
                item.put("planStorageDate", cost.getPlanStorageDate().substring(0, 10));
                item.put("assetsTypeName", AssetsTypeEnum.getNameByValue(cost.getAssetsType()));
                usedAmount = usedAmount.add(cost.getPlanAmount());
                List<AssetsAdvancePay> subList = new ArrayList<>();
                String costId = cost.getId();
                if (costDetailMap.containsKey(costId)) {
                    subList = costDetailMap.get(costId);
                }
                List<AssetsAdvancePay> sortSubList = subList.stream().sorted(
                        Comparator.nullsLast(Comparator.comparing(AssetsAdvancePay::getPlanPayDate,
                                Comparator.nullsLast(String::compareTo)))).collect(Collectors.toList());
                List<Map<String, Object>> newSortSubList = new ArrayList<>(sortSubList.size());
                int paySort = 1;
                for (AssetsAdvancePay assetsAdvancePay : sortSubList) {
                    Map<String, Object> payItem = ObjectUtils.object2Map(assetsAdvancePay);
                    payItem.put("sort", paySort);
                    newSortSubList.add(payItem);
                    paySort++;
                }
                item.put("subList", newSortSubList);
                resultCostList.add(item);
                sortCost++;
            }
            dataMap.put("costList", resultCostList);
            dataMap.put("leftAmount", assets.getGreenAmount().subtract(usedAmount));
            dataMap.put("planCloseDate", assets.getPlanCloseDate());
        }

        return dataMap;
    }

    @Override
    @Transactional
    public void updateAssetsForecastInfo(AssetsMonthDetail assetsMonthDetail, List<AssetsOrderForecastDto> orderForecastList, List<AssetsCostDto> costList) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        Assets assets = assetsDao.selectById(assetsMonthDetail.getBusinessId());
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，固资信息不存在！");
        }
        String currentYear = assetsMonthDetail.getInfoYear();
        BigDecimal currentYearForecast = new BigDecimal(0);
        if (assets.getStatus() > 2) {
            currentYear = currentTime.substring(0, 4);
            ForecastDataDto dto = buildForecastData(assets, orderForecastList, costList, currentUser.getId(), currentTime);
            if (!ObjectUtils.isEmpty(dto.getCostAddList())) {
                assetsCostDao.insertBatch(dto.getCostAddList());
            }
            if (!ObjectUtils.isEmpty(dto.getCostUpdateList())) {
                assetsCostDao.updateBatchById(dto.getCostUpdateList());
            }
            if (!ObjectUtils.isEmpty(dto.getCostDeleteList())) {
                assetsCostDao.updateStatusById(dto.getCostDeleteList(), currentUser.getId(), currentTime);
            }
            if (!ObjectUtils.isEmpty(dto.getPayAddList())) {
                assetsAdvancePayDao.insertBatch(dto.getPayAddList());
            }
            if (!ObjectUtils.isEmpty(dto.getPayUpdateList())) {
                assetsAdvancePayDao.updateBatchById(dto.getPayUpdateList());
            }
            if (!ObjectUtils.isEmpty(dto.getPayDeleteList())) {
                assetsAdvancePayDao.updateStatusById(dto.getPayDeleteList(), currentUser.getId(), currentTime);
            }
//            AssetsMonthDetail oldInfo = null;
//            List<AssetsMonthDetail> oldList = assetsMonthDetailDao.getAssetsMonthInfo(assetsMonthDetail.getBusinessId(), assetsMonthDetail.getInfoYear());
//            for (AssetsMonthDetail detail : oldList) {
//                if (detail.getBusinessType() == 3) {
//                    oldInfo = detail;
//                }
//            }
            AssetsMonthDetail detail = dto.getAssetsMonthDetail();
            AssetsMonthDetail oldInfo = assetsMonthDetailDao.selectById(detail.getId());
            if (!ObjectUtils.isEmpty(oldInfo)) {
                assetsMonthDetailDao.updateById(detail);
            } else {
                assetsMonthDetailDao.insert(detail);
            }
            currentYearForecast = DecimalUtils.add(DecimalUtils.add(detail.getJanAmount(), detail.getFebAmount(), detail.getMarAmount(),
                    detail.getAprAmount()), DecimalUtils.add(detail.getMayAmount(), detail.getJunAmount(),
                    detail.getJulAmount(), detail.getAugAmount()), DecimalUtils.add(detail.getSepAmount(),
                    detail.getOctAmount(), detail.getNovAmount(), detail.getDecAmount()), BigDecimal.ZERO);
            AssetsStatistics assetsStatistics = assetsStatisticsDao.getStatisticsByAssets(assets.getId(), currentYear);

            if (!BigDecimal.ZERO.equals(DecimalUtils.subtract(assetsStatistics.getForecastAmount(), currentYearForecast))) {
                assetsStatistics.setForecastAmount(currentYearForecast);
                assetsStatistics.setUpdateUser(currentUser.getId());
                assetsStatistics.setUpdateTime(currentTime);
                assetsStatisticsDao.updateById(assetsStatistics);
            }

        } else {
            AssetsMonthDetail oldInfo = null;
            if (StringUtils.isEmpty(assetsMonthDetail.getId())) {
                List<AssetsMonthDetail> oldList = assetsMonthDetailDao.getAssetsMonthInfo(assetsMonthDetail.getBusinessId(), assetsMonthDetail.getInfoYear());
                for (AssetsMonthDetail detail : oldList) {
                    if (detail.getBusinessType() == 3) {
                        oldInfo = detail;
                    }
                }
                if (ObjectUtils.isEmpty(oldInfo)) {
                    assetsMonthDetail.setInfoYear(StringUtils.isEmpty(assetsMonthDetail.getInfoYear()) ? assets.getCurrentYear() : assetsMonthDetail.getInfoYear());
                    assetsMonthDetail.setId(SnowFlake.nextIdStr());
                    assetsMonthDetail.setBusinessType(3);
                    assetsMonthDetail.setBusinessId(assets.getId());
                    assetsMonthDetail.setCreateUser(currentUser.getId());
                    assetsMonthDetail.setCreateTime(currentTime);
                    assetsMonthDetailDao.insert(assetsMonthDetail);
                    return;
                }
            } else {
                oldInfo = assetsMonthDetailDao.selectById(assetsMonthDetail.getId());
            }
            oldInfo.setFebAmount(assetsMonthDetail.getFebAmount());
            oldInfo.setJanAmount(assetsMonthDetail.getJanAmount());
            oldInfo.setMarAmount(assetsMonthDetail.getMarAmount());
            oldInfo.setAprAmount(assetsMonthDetail.getAprAmount());
            oldInfo.setMayAmount(assetsMonthDetail.getMayAmount());
            oldInfo.setJunAmount(assetsMonthDetail.getJunAmount());
            oldInfo.setJulAmount(assetsMonthDetail.getJulAmount());
            oldInfo.setAugAmount(assetsMonthDetail.getAugAmount());
            oldInfo.setSepAmount(assetsMonthDetail.getSepAmount());
            oldInfo.setOctAmount(assetsMonthDetail.getOctAmount());
            oldInfo.setNovAmount(assetsMonthDetail.getNovAmount());
            oldInfo.setDecAmount(assetsMonthDetail.getDecAmount());
            oldInfo.setUpdateUser(currentUser.getId());
            oldInfo.setUpdateTime(currentTime);
            assetsMonthDetailDao.updateById(oldInfo);
            currentYearForecast = DecimalUtils.add(DecimalUtils.add(assetsMonthDetail.getJanAmount(), assetsMonthDetail.getFebAmount(), assetsMonthDetail.getMarAmount(),
                    assetsMonthDetail.getAprAmount()), DecimalUtils.add(assetsMonthDetail.getMayAmount(), assetsMonthDetail.getJunAmount(),
                    assetsMonthDetail.getJulAmount(), assetsMonthDetail.getAugAmount()), DecimalUtils.add(assetsMonthDetail.getSepAmount(),
                    assetsMonthDetail.getOctAmount(), assetsMonthDetail.getNovAmount(), assetsMonthDetail.getDecAmount()), BigDecimal.ZERO);
            AssetsStatistics assetsStatistics = assetsStatisticsDao.getStatisticsByAssets(assets.getId(), currentYear);
            if (!BigDecimal.ZERO.equals(DecimalUtils.subtract(assetsStatistics.getForecastAmount(), currentYearForecast))) {
                assetsStatistics.setForecastAmount(currentYearForecast);
                assetsStatistics.setUpdateUser(currentUser.getId());
                assetsStatistics.setUpdateTime(currentTime);
                assetsStatisticsDao.updateById(assetsStatistics);
            }

        }
        assets.setCurrentYearForecast(currentYearForecast);
        assetsDao.updateById(assets);
    }

    @Override
    @Transactional
    public void checkAssetsCost() {
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 100000);

        Map<String, List<AssetsOrder>> assetsOrderMap = new HashMap<>();
        // 获取全部订单
        List<AssetsOrder> orderList = assetsOrderDao.getAssetsOrderList(queryParam);
        for (AssetsOrder orderInfo : orderList) {
            List<AssetsOrder> orderInfoList = assetsOrderMap.containsKey(orderInfo.getAssetsId()) ? assetsOrderMap.get(orderInfo.getAssetsId()) : new ArrayList<>();
            orderInfoList.add(orderInfo);
            assetsOrderMap.put(orderInfo.getAssetsId(), orderInfoList);
        }
        // 获取全部补充订单
        List<AssetsOrderExpand> expandOrderList = assetsOrderExpandDao.pageAssetsOrderExpandInfo(queryParam);
        for (AssetsOrderExpand exp : expandOrderList) {
            AssetsOrder order = new AssetsOrder();
            String assetsId = exp.getAssetsId();
            order.setAssetsId(assetsId);
            order.setAssetsNo(exp.getAssetsNo());
            order.setEffectiveDate(exp.getEffectiveDate());
            order.setCloseDate(exp.getEffectiveDate());
            order.setStatus(2);
            order.setUntaxedAmount(exp.getUntaxedAmount());
            List<AssetsOrder> orderInfoList = assetsOrderMap.containsKey(assetsId) ? assetsOrderMap.get(assetsId) : new ArrayList<>();
            orderInfoList.add(order);
            assetsOrderMap.put(assetsId, orderInfoList);
        }
        // 获取全部预付
        List<AssetsOrderPay> payList = assetsOrderPayDao.pageAssetsOrderPayInfo(queryParam);
        Map<String, Map<String, List<AssetsOrderPay>>> orderPayMap = new HashMap<>();
        for (AssetsOrderPay pay : payList) {
            String orderNo = pay.getOrderNo();
            Map<String, List<AssetsOrderPay>> payYearMap = orderPayMap.containsKey(orderNo) ? orderPayMap.get(orderNo) : new HashMap<>();
            String yearKey = pay.getEffectiveDate().substring(0, 4);
            List<AssetsOrderPay> yearPayList = payYearMap.containsKey(yearKey) ? payYearMap.get(yearKey) : new ArrayList<>();
            yearPayList.add(pay);
            payYearMap.put(yearKey, yearPayList);
            orderPayMap.put(orderNo, payYearMap);
        }
        // 获取全部固资项目
        List<Assets> assetsList = assetsDao.getAllAssetsList();
        Map<String, BigDecimal> assetsYearAmountMap = new HashMap<>();
        String currentYear = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD).substring(0, 4);
        Map<String, String> usedOrderPayMap = new HashMap<>();
        Map<String, AssetsStatistics> statisticsMap = assetsStatisticsDao.getAllAssetsStatisticsMap();
        List<AssetsStatistics> updateList = new ArrayList<>();
        List<AssetsStatistics> addList = new ArrayList<>();
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        // 匹配固资项目与订单数据
        for (Assets assets : assetsList) {
            int assetsStartYear = Integer.valueOf(assets.getCurrentYear());
            List<String> yearList = new ArrayList<>();
            for (int i = assetsStartYear; i <= Integer.valueOf(currentYear); i++) {
                yearList.add(String.valueOf(i));
            }
            String assetsId = assets.getId();
            List<AssetsOrder> assetsOrderList = assetsOrderMap.get(assetsId);
            // 不存在订单信息，实际花费为0
            if (ObjectUtils.isEmpty(assetsOrderList)) {
                for (String year : yearList) {
                    assetsYearAmountMap.put(assetsId + "-" + year, new BigDecimal(0));
                }
                continue;
            }
            // 匹配订单与预付年度
            // 求和计算实际花费
            for (AssetsOrder orderInfo : assetsOrderList) {
                Map<String, List<AssetsOrderPay>> payMap = new HashMap<>();
                String orderNo = orderInfo.getOrderNo();
                if (!StringUtils.isEmpty(orderNo)) {
                    orderNo = orderInfo.getOrderNo().toUpperCase();
                    payMap = usedOrderPayMap.containsKey(orderNo) ? new HashMap<>() : orderPayMap.get(orderNo);
                }
                // open订单处理
                if (orderInfo.getStatus() == 2) {
                    String costYear = orderInfo.getCloseDate().substring(0, 4);
                    String costYearKey = assetsId + "-" + costYear;
                    if (ObjectUtils.isEmpty(payMap)) {
                        // open订单，不存在预付，全部计入close年度
                        BigDecimal amount = assetsYearAmountMap.containsKey(costYearKey) ? assetsYearAmountMap.get(costYearKey) : new BigDecimal(0);
                        assetsYearAmountMap.put(costYearKey, DecimalUtils.add(orderInfo.getUntaxedAmount(), amount));
                        for (String year : yearList) {
                            if (StringUtils.equals(year, costYear)) {
                                continue;
                            }
                            String yearKey = assetsId + "-" + year;
                            BigDecimal yearAmount = assetsYearAmountMap.containsKey(yearKey) ? assetsYearAmountMap.get(yearKey) : new BigDecimal(0);
                            assetsYearAmountMap.put(yearKey, yearAmount);
                        }
                    } else {
                        // open订单，存在预付，预付计入预付年度，除预付外数据计入close年度
                        BigDecimal allPayAmount = BigDecimal.ZERO;
                        for (String year : yearList) {
                            String yearKey = assetsId + "-" + year;
                            BigDecimal yearAmount = assetsYearAmountMap.containsKey(yearKey) ? assetsYearAmountMap.get(yearKey) : new BigDecimal(0);
                            if (!payMap.containsKey(year)) {
                                assetsYearAmountMap.put(yearKey, yearAmount);
                                continue;
                            }
                            List<AssetsOrderPay> orderPayList = payMap.get(year);
                            for (AssetsOrderPay orderPay : orderPayList) {
                                yearAmount = DecimalUtils.add(yearAmount, orderPay.getUntaxedAmount());
                                allPayAmount = DecimalUtils.add(allPayAmount, orderPay.getUntaxedAmount());
                            }
                            assetsYearAmountMap.put(yearKey, yearAmount);
                        }
                        BigDecimal yearCostAmount = DecimalUtils.subtract(orderInfo.getUntaxedAmount(), allPayAmount);
                        BigDecimal yearAmount = assetsYearAmountMap.containsKey(costYearKey) ? assetsYearAmountMap.get(costYearKey) : BigDecimal.ZERO;
                        yearAmount = DecimalUtils.add(yearAmount, yearCostAmount);
                        assetsYearAmountMap.put(costYearKey, yearAmount);
                    }
                } else {
                    // 未结订单处理
                    if (ObjectUtils.isEmpty(payMap)) {
                        // 不存在预付数据
                        for (String year : yearList) {
                            String yearKey = assetsId + "-" + year;
                            BigDecimal yearAmount = assetsYearAmountMap.containsKey(yearKey) ? assetsYearAmountMap.get(yearKey) : new BigDecimal(0);
                            assetsYearAmountMap.put(yearKey, yearAmount);
                        }
                        continue;
                    }
                    // 存在预付数据
                    for (String year : yearList) {
                        String yearKey = assetsId + "-" + year;
                        BigDecimal yearAmount = assetsYearAmountMap.containsKey(yearKey) ? assetsYearAmountMap.get(yearKey) : new BigDecimal(0);
                        if (!payMap.containsKey(year)) {
                            assetsYearAmountMap.put(yearKey, yearAmount);
                            continue;
                        }
                        List<AssetsOrderPay> orderPayList = payMap.get(year);
                        for (AssetsOrderPay orderPay : orderPayList) {
                            yearAmount = DecimalUtils.add(yearAmount, orderPay.getUntaxedAmount());
                        }
                        assetsYearAmountMap.put(yearKey, yearAmount);
                    }
                }
                usedOrderPayMap.put(orderNo, orderNo);
            }
        }
        // 组装入库数据
        for (String assetsKey : assetsYearAmountMap.keySet()) {
            AssetsStatistics statistics = new AssetsStatistics();
            if (statisticsMap.containsKey(assetsKey)) {
                statistics = statisticsMap.get(assetsKey);
                statistics.setActualAmount(assetsYearAmountMap.get(assetsKey));
                statistics.setUpdateTime(currentTime);
                statistics.setUpdateUser(currentUser.getId());
                updateList.add(statistics);
                continue;
            }
            statistics.setActualAmount(assetsYearAmountMap.get(assetsKey));
            statistics.setId(SnowFlake.nextIdStr());
            List<String> dList = Arrays.asList(assetsKey.split("-"));
            statistics.setCurrentYear(dList.get(1));
            statistics.setSortNum(0);
            statistics.setAssetsId(dList.get(0));
            statistics.setPlanAmount(BigDecimal.ZERO);
            statistics.setForecastAmount(BigDecimal.ZERO);
            statistics.setCreateTime(currentTime);
            statistics.setCreateUser(currentUser.getId());
            addList.add(statistics);
        }
        // 数据入库
        if (!updateList.isEmpty()) {
            assetsStatisticsDao.updateBatchById(updateList);
        }
        if (!addList.isEmpty()) {
            assetsStatisticsDao.insertBatch(addList);
        }
    }

    @Override
    public void generateAssetsStatistics() {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<Assets> assetsList = assetsDao.getEffectiveAssets();
        Map<String, Map<String, String>> statisticMap = assetsStatisticsDao.getAssetsStatisticsMap();
        String currentYear = TimeUtils.getYear();
        List<AssetsStatistics> statisticsList = new ArrayList<>();
        for (Assets assets : assetsList) {
            String key = assets.getId() + "-" + currentYear;
            if (statisticMap.containsKey(key)) {
                continue;
            }
            AssetsStatistics statistics = new AssetsStatistics();
            statistics.setId(SnowFlake.nextIdStr());
            statistics.setCurrentYear(currentYear);
            statistics.setAssetsId(assets.getId());
            statistics.setSortNum(1);
            statistics.setPlanAmount(new BigDecimal(0));
            statistics.setForecastAmount(new BigDecimal(0));
            statistics.setActualAmount(new BigDecimal(0));
            statistics.setCreateUser(currentUser.getId());
            statistics.setCreateTime(currentTime);
            statisticsList.add(statistics);
        }
        if (!statisticsList.isEmpty()) {
            assetsStatisticsDao.insertBatch(statisticsList);
        }
    }

    @Override
    public void updateAssetsRecommend(String id) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        Assets assets = assetsDao.selectById(id);
        if (ObjectUtils.isEmpty(assets)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资信息不存在！");
        }
        assets.setRecommend(assets.getRecommend() == 0 ? 1 : 0);
        assets.setUpdateUser(currentUser.getId());
        assets.setUpdateTime(currentTime);
        assetsDao.updateById(assets);
    }

    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private ImportAssetsInfoDto covertToBean(String[] record) {
        ImportAssetsInfoDto assetsInfo = new ImportAssetsInfoDto();
        assetsInfo.setPlant(record[1].trim());
        assetsInfo.setAssetsNo(record[2].trim());
        assetsInfo.setDepartment(record[3].trim());
        assetsInfo.setProjectName(record[4].trim());
        assetsInfo.setProjectNameEng(record[5].trim());
        assetsInfo.setProjectManage(record[6].trim());
        assetsInfo.setProjectType(record[7].trim());
        assetsInfo.setCurrentYear(record[8].trim());
        assetsInfo.setGreenAmount(new BigDecimal(record[9]));
        assetsInfo.setStatus(record[10].trim());
        assetsInfo.setApproveTime(record[11].trim());
        assetsInfo.setBudget(record[12].trim());
        return assetsInfo;
    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("工厂不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 20) {
                addRowError("工厂长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[3].trim())) {
            addRowError("申请部门不能为空", rowErrors);
        } else {
            if (record[3].trim().length() > 100) {
                addRowError("申请部门长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("项目描述不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 100) {
                addRowError("项目描述字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[6].trim())) {
            addRowError("项目负责人不能为空", rowErrors);
        } else {
            if (record[6].trim().length() > 100) {
                addRowError("项目负责人字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[7].trim())) {
            addRowError("项目类型不能为空", rowErrors);
        } else {
            if (record[7].trim().length() > 20) {
                addRowError("项目类型长度不能超过20", rowErrors);
            }
        }
        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 补全数据
     *
     * @param originalList 原始数据
     * @param startNum     数据起始值
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<Assets> originalList, int startNum, String userId) {
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        List<Map<String, Object>> resultList = new ArrayList<>();
        int sort = startNum + 1;
        for (Assets assetsInfo : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(assetsInfo);
            item.put("sort", sort);
            item.put("departmentName", departmentMap.containsKey(assetsInfo.getDepartment()) ? departmentMap.get(assetsInfo.getDepartment()).get("name") : "");
            item.put("statusName", AssetsStatusEnum.getNameByValue(assetsInfo.getStatus()));
            item.put("manageName", userMap.containsKey(assetsInfo.getProjectManage()) ? userMap.get(assetsInfo.getProjectManage()).get("name") : "");
//            item.put("typeName", assetsInfo.getProjectType() == 1 ? "XG" : "OTHER");
            item.put("modifyPermission", StringUtils.equals(userId, assetsInfo.getProjectManage()));
            resultList.add(item);
            sort++;
        }
        return resultList;
    }

    /**
     * 创建统计信息
     *
     * @param assets 固资信息
     * @return 固资统计信息
     */
    private AssetsStatistics buildStatistics(Assets assets) {
        AssetsStatistics assetsStatistics = new AssetsStatistics();
        assetsStatistics.setId(SnowFlake.nextIdStr());
        assetsStatistics.setAssetsId(assets.getId());
        assetsStatistics.setCurrentYear(assets.getCurrentYear());
        assetsStatistics.setCreateTime(assets.getCreateTime());
        assetsStatistics.setCreateUser(assets.getCreateUser());
        assetsStatistics.setPlanAmount(assets.getCurrentYearAmount());
        assetsStatistics.setForecastAmount(assets.getCurrentYearForecast());
        assetsStatistics.setActualAmount(assets.getCurrentYearActual());
        return assetsStatistics;
    }

    private ForecastDataDto buildForecastData(Assets assets, List<AssetsOrderForecastDto> orderForecastList,
                                              List<AssetsCostDto> costList, String userId, String currentTime) {
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        queryParam.put("assetsId", assets.getId());
        queryParam.put("status", 1);
        List<AssetsCost> dbList = assetsCostDao.pageAssetsCostInfo(queryParam);
        Map<String, AssetsCost> dbCostMap = new HashMap<>(dbList.size());
        for (AssetsCost cost : dbList) {
            dbCostMap.put(cost.getId(), cost);
        }
        List<AssetsCost> costAddList = new ArrayList<>();
        List<AssetsCost> costUpdateList = new ArrayList<>();
        Map<String, AssetsCost> deleteCostMap = new HashMap<>(dbCostMap);

        ForecastDataDto resultDto = new ForecastDataDto();
        List<AssetsAdvancePay> dbAdvanceList;
        if (dbList.size() > 0) {
            dbAdvanceList = assetsAdvancePayDao.getEffectiveAdvancePayList(dbList.stream().map(AssetsCost::getId).collect(Collectors.toList()));
        } else {
            dbAdvanceList = new ArrayList<>();
        }
        Map<String, AssetsAdvancePay> dbAdvanceMap = new HashMap<>(dbAdvanceList.size());
        for (AssetsAdvancePay advancePay : dbAdvanceList) {
            dbAdvanceMap.put(advancePay.getId(), advancePay);
        }
        List<AssetsAdvancePay> forecastAddList = new ArrayList<>();
        List<AssetsAdvancePay> forecastUpdateList = new ArrayList<>();
        Map<String, AssetsAdvancePay> deletePayMap = new HashMap<>(dbAdvanceMap);
        AssetsMonthDetail assetsMonthDetail = assetsMonthDetailDao.getAssetsMonthInfoByType(assets.getId(), currentTime.substring(0, 4), 3);
        // 构建订单预测数据
        Map<Integer, BigDecimal> monthAmountMap = new HashMap<>();
        for (AssetsOrderForecastDto forecastDto : orderForecastList) {
            String costId = forecastDto.getId();
            BigDecimal orderTotalAmount = forecastDto.getUntaxedAmount();
            BigDecimal orderCostAmount = forecastDto.getTotalCost();
            if (StringUtils.isEmpty(costId)) {
                costId = SnowFlake.nextIdStr();
                AssetsCost cost = new AssetsCost();
                cost.setId(costId);
                cost.setAssetsId(assets.getId());
                cost.setSourceType(1);
                cost.setSourceId(forecastDto.getOrderId());
                cost.setStatus(1);
                cost.setCreateUser(userId);
                cost.setCreateTime(currentTime);
                costAddList.add(cost);
            } else {
                AssetsCost cost = dbCostMap.get(costId);
                cost.setUpdateUser(userId);
                cost.setUpdateTime(currentTime);
                costUpdateList.add(cost);
                deleteCostMap.remove(costId);
            }
            List<AssetsAdvancePay> orderForecasts = forecastDto.getSubList();
//            BigDecimal payAmount = BigDecimal.ZERO;
            boolean storageFlag = false;
            int storageMonth = 0;
            for (AssetsAdvancePay forecast : orderForecasts) {
                String advanceId = forecast.getId();
                int month = Integer.parseInt(forecast.getPlanPayDate().substring(5, 7));
                BigDecimal amount = monthAmountMap.containsKey(month) ? monthAmountMap.get(month) : BigDecimal.ZERO;
                if (StringUtils.isEmpty(advanceId)) {
                    advanceId = SnowFlake.nextIdStr();
                    forecast.setId(advanceId);
                    forecast.setCostId(costId);
                    forecast.setCreateUser(userId);
                    forecast.setCreateTime(currentTime);
                    forecast.setStatus(1);
                    forecastAddList.add(forecast);
                } else {
                    forecast.setUpdateUser(userId);
                    forecast.setUpdateTime(currentTime);
                    forecast.setStatus(1);
                    forecastUpdateList.add(forecast);
                    deletePayMap.remove(advanceId);
                }
                if (forecast.getPayType() == 1) {
                    BigDecimal payDetailAmount = DecimalUtils.multiply(DecimalUtils.divide(new BigDecimal(forecast.getPlanPayRate()), new BigDecimal(100)), orderTotalAmount);
                    monthAmountMap.put(month, DecimalUtils.add(amount, payDetailAmount));
                    orderCostAmount = DecimalUtils.add(orderCostAmount, payDetailAmount);
                } else {
                    storageFlag = true;
                    storageMonth = month;
                }
            }
            if (storageFlag) {
                BigDecimal amount = monthAmountMap.containsKey(storageMonth) ? monthAmountMap.get(storageMonth) : BigDecimal.ZERO;
                BigDecimal storageAmount = DecimalUtils.subtract(orderTotalAmount, orderCostAmount);
                monthAmountMap.put(storageMonth, DecimalUtils.add(amount, storageAmount));
            }
        }

        // 构建新增订单预测数据
        for (AssetsCostDto assetsCostDto : costList) {
            String costId = assetsCostDto.getId();
            boolean changeStorageFlag = false;
            BigDecimal orderTotalAmount = assetsCostDto.getPlanAmount();
            BigDecimal orderCostAmount = BigDecimal.ZERO;
            int storageMonth = Integer.parseInt(assetsCostDto.getPlanStorageDate().substring(5, 7));
            if (StringUtils.isEmpty(costId)) {
                costId = SnowFlake.nextIdStr();
                AssetsCost cost = new AssetsCost();
                cost.setId(costId);
                cost.setAssetsId(assets.getId());
                cost.setSourceType(2);
                cost.setCostName(assetsCostDto.getCostName());
                cost.setAssetsType(assetsCostDto.getAssetsType());
                cost.setPlanAmount(assetsCostDto.getPlanAmount());
                cost.setPlanStorageDate(assetsCostDto.getPlanStorageDate());
                cost.setStatus(1);
                cost.setCreateUser(userId);
                cost.setCreateTime(currentTime);
                costAddList.add(cost);
                // 入库数据组装
                AssetsAdvancePay assetsAdvancePay = new AssetsAdvancePay();
                assetsAdvancePay.setId(SnowFlake.nextIdStr());
                assetsAdvancePay.setCostId(costId);
                assetsAdvancePay.setPlanPayDate(assetsCostDto.getPlanStorageDate());
                assetsAdvancePay.setPayType(2);
                assetsAdvancePay.setCreateUser(userId);
                assetsAdvancePay.setCreateTime(currentTime);
                assetsAdvancePay.setStatus(1);
                forecastAddList.add(assetsAdvancePay);
            } else {
                AssetsCost cost = dbCostMap.get(costId);
                cost.setCostName(assetsCostDto.getCostName());
                cost.setAssetsType(assetsCostDto.getAssetsType());
                if (!BigDecimal.ZERO.equals(DecimalUtils.subtract(assetsCostDto.getPlanAmount(), cost.getPlanAmount())) ||
                        !StringUtils.equals(assetsCostDto.getPlanStorageDate(), cost.getPlanStorageDate())) {
                    changeStorageFlag = true;
                }
                cost.setPlanAmount(assetsCostDto.getPlanAmount());
                cost.setPlanStorageDate(assetsCostDto.getPlanStorageDate());
                cost.setUpdateUser(userId);
                cost.setUpdateTime(currentTime);
                costUpdateList.add(cost);
                deleteCostMap.remove(costId);
            }
            // 新增数据，不存在子信息
            if (ObjectUtils.isEmpty(assetsCostDto.getSubList())) {
                continue;
            }
//            else if (assetsCostDto.getSubList().size() == 1 && ObjectUtils.isEmpty(assetsCostDto.getSubList().get(0))) {
//                continue;
//            }
            // 修改或存在预付信息
            List<AssetsAdvancePay> advancePays = assetsCostDto.getSubList();
            for (AssetsAdvancePay advancePay : advancePays) {
                if (StringUtils.isEmpty(advancePay.getPlanPayDate())) {
                    continue;
                }
                String advanceId = advancePay.getId();
                if (advancePay.getPayType() == 2) {
                    if (changeStorageFlag) {
                        advancePay.setPlanPayDate(assetsCostDto.getPlanStorageDate());
                    }
                } else {
                    int month = Integer.parseInt(advancePay.getPlanPayDate().substring(5, 7));
                    BigDecimal amount = monthAmountMap.containsKey(month) ? monthAmountMap.get(month) : BigDecimal.ZERO;
                    BigDecimal payDetailAmount = DecimalUtils.multiply(DecimalUtils.divide(new BigDecimal(advancePay.getPlanPayRate()), new BigDecimal(100)), orderTotalAmount);
                    monthAmountMap.put(month, DecimalUtils.add(amount, payDetailAmount));
                    orderCostAmount = DecimalUtils.add(orderCostAmount, payDetailAmount);
                }
                if (StringUtils.isEmpty(advanceId)) {
                    advanceId = SnowFlake.nextIdStr();
                    advancePay.setId(advanceId);
                    advancePay.setCostId(costId);
                    advancePay.setPayType(1);
                    advancePay.setCreateUser(userId);
                    advancePay.setCreateTime(currentTime);
                    advancePay.setStatus(1);
                    forecastAddList.add(advancePay);
                } else {
                    advancePay.setUpdateUser(userId);
                    advancePay.setUpdateTime(currentTime);
                    advancePay.setStatus(1);
                    forecastUpdateList.add(advancePay);
                    deletePayMap.remove(advanceId);
                }
            }
            BigDecimal amount = monthAmountMap.containsKey(storageMonth) ? monthAmountMap.get(storageMonth) : BigDecimal.ZERO;
            BigDecimal storageAmount = DecimalUtils.subtract(orderTotalAmount, orderCostAmount);
            monthAmountMap.put(storageMonth, DecimalUtils.add(amount, storageAmount));
        }
        resultDto.setCostAddList(costAddList);
        resultDto.setCostUpdateList(costUpdateList);
        resultDto.setCostDeleteList(new ArrayList<>(deleteCostMap.keySet()));
        resultDto.setPayAddList(forecastAddList);
        resultDto.setPayUpdateList(forecastUpdateList);
        resultDto.setPayDeleteList(new ArrayList<>(deletePayMap.keySet()));

        // 月度预测统计数据
        AssetsMonthDetail newAssetsMonthDetail = new AssetsMonthDetail(BigDecimal.ZERO);
        if (ObjectUtils.isEmpty(assetsMonthDetail)) {
            newAssetsMonthDetail.setId(SnowFlake.nextIdStr());
            newAssetsMonthDetail.setBusinessType(3);
            newAssetsMonthDetail.setBusinessId(assets.getId());
            newAssetsMonthDetail.setInfoYear(currentTime.substring(0, 4));
            newAssetsMonthDetail.setCreateUser(userId);
            newAssetsMonthDetail.setCreateTime(currentTime);
        } else {
            newAssetsMonthDetail.setId(assetsMonthDetail.getId());
            newAssetsMonthDetail.setBusinessType(assetsMonthDetail.getBusinessType());
            newAssetsMonthDetail.setBusinessId(assetsMonthDetail.getBusinessId());
            newAssetsMonthDetail.setInfoYear(assetsMonthDetail.getInfoYear());
            newAssetsMonthDetail.setCreateUser(assetsMonthDetail.getCreateUser());
            newAssetsMonthDetail.setCreateTime(assetsMonthDetail.getCreateTime());
        }
        if (!monthAmountMap.isEmpty()) {
            for (Integer month : monthAmountMap.keySet()) {
                if (month == 1) {
                    newAssetsMonthDetail.setJanAmount(monthAmountMap.get(1));
                } else if (month == 2) {
                    newAssetsMonthDetail.setFebAmount(monthAmountMap.get(2));
                } else if (month == 3) {
                    newAssetsMonthDetail.setMarAmount(monthAmountMap.get(3));
                } else if (month == 4) {
                    newAssetsMonthDetail.setAprAmount(monthAmountMap.get(4));
                } else if (month == 5) {
                    newAssetsMonthDetail.setMayAmount(monthAmountMap.get(5));
                } else if (month == 6) {
                    newAssetsMonthDetail.setJunAmount(monthAmountMap.get(6));
                } else if (month == 7) {
                    newAssetsMonthDetail.setJulAmount(monthAmountMap.get(7));
                } else if (month == 8) {
                    newAssetsMonthDetail.setAugAmount(monthAmountMap.get(8));
                } else if (month == 9) {
                    newAssetsMonthDetail.setSepAmount(monthAmountMap.get(9));
                } else if (month == 10) {
                    newAssetsMonthDetail.setOctAmount(monthAmountMap.get(10));
                } else if (month == 11) {
                    newAssetsMonthDetail.setNovAmount(monthAmountMap.get(11));
                } else if (month == 12) {
                    newAssetsMonthDetail.setDecAmount(monthAmountMap.get(12));
                }
            }
        } else {
            newAssetsMonthDetail.setUpdateUser(userId);
            newAssetsMonthDetail.setUpdateTime(currentTime);
        }
        resultDto.setAssetsMonthDetail(newAssetsMonthDetail);
        return resultDto;
    }


}
